package com.mueblesgl.proyecto.produccion;

import java.util.Hashtable;
import java.util.Vector;

import com.mueblesgl.proyecto.entidades.ProcedimientoRecurso;
import com.mueblesgl.proyecto.entidades.Recurso;
import com.mueblesgl.proyecto.producto.ServiceProducto;
import com.mueblesgl.proyecto.util.Util;

public class AlgortimoPlanificacion {

	private String[][] tablero;
	private Hashtable<Integer, Integer> resultado;  //Cambiar por hastable
	private int filas;
	private int columnas;
	private int cantidadVariables;
	
	public AlgortimoPlanificacion() {
		resultado = new Hashtable<Integer, Integer>();
	}
	
	public String[][] iniciacionDeMatriz(int[] idProductos) {
		
		ServiceProducto serviceProducto = new ServiceProducto(); 
		ServiceProduccion serviceProduccion = new ServiceProduccion();
		
		Vector<Recurso> recursos = obtenerMaterialesTotales(idProductos);
		
		cantidadVariables = recursos.size();
		
		final int CANTIDAD_FILAS_FIJAS_MATRIZ = 4;
		
		filas = CANTIDAD_FILAS_FIJAS_MATRIZ + cantidadVariables;
		columnas = idProductos.length + cantidadVariables + CANTIDAD_FILAS_FIJAS_MATRIZ;
		
		tablero = new String[filas][columnas];
		
				
		//*************** FILA 0 *****************//
		
		tablero[0][0] = "Cj";
		tablero[0][1] = "";
		
		int columna = 0;
		for(int i=0; i<idProductos.length; i++) {
			columna = i + 2;
			tablero[0][columna] = Double.toString(serviceProducto.consultarProducto(idProductos[i]).getPrecio());  
		}
		
		for(int i=0; i<cantidadVariables; i++) {
			columna++;
			tablero[0][columna] = "0";  
		}
		
		columna++;
		tablero[0][columna] = "bi";
		columna++;
		tablero[0][columna] = "RAZON";

		//*************** FILA 1 *****************//
		
		tablero[1][0] = "Cb";
		tablero[1][1] = "Xb";
		
		
		columna = 0;
		for(int i=0; i<idProductos.length; i++) {
			columna = i + 2;
			tablero[1][columna] = "X" + serviceProducto.consultarProducto(idProductos[i]).getIdProducto();  
		}
				
		for(int i=0; i<cantidadVariables; i++) {
			columna++;
			tablero[1][columna] = "S" + recursos.get(i).getIdRecurso();  
		}
		
			
		tablero[1][columnas - 2] = " ";		
		tablero[1][columnas - 1] = " ";
		
		//*************** FILAS DE RESTRICCIONES DE MATERIALES *****************//
		
		for(int i=2; i<cantidadVariables + 2; i++) {
			tablero[i][0] = "0";
			tablero[i][1] = "S" + recursos.get(i - 2).getIdRecurso();
			System.out.println(tablero[i][1]);
			int j;
			for(j=2; j<idProductos.length + 2; j++) {				
				Vector<ProcedimientoRecurso> procedimientoRecursos = serviceProduccion.obtenerRecursosDetalleProcedimiento(idProductos[j - 2]);
				for(ProcedimientoRecurso pr : procedimientoRecursos) {
					System.out.println("ESTOY ANTES DEL IF DE: " + Util.sacarLetra(tablero[i][1], "S"));
					if(Integer.parseInt(Util.sacarLetra(tablero[i][1], "S")) == pr.getIdRecurso()) {
						System.out.println("ESTOY DENTRO DEL IF");
						tablero[i][j] = Integer.toString(pr.getCantidad());
						System.out.println("EL VALOR DE ESTA PARTE ES: " + tablero[i][j]);
						
						break;
					} else {
						tablero[i][j] = "0";
					}
				}			
				
			}
			
			for(int k=j; k<cantidadVariables + j; k++) {
				if(tablero[i][1].equals(tablero[1][k])) {
					tablero[i][k] = "1";
				} else { 
					tablero[i][k] = "0";
				}				
			}
			tablero[i][columnas - 2] = String.valueOf(recursos.get(i - 2).getCantidad());		
			tablero[i][columnas - 1] = "";
		}
		
		
		
		//*************** FILA n-1 *****************//
		
		tablero[filas-2][0] = "Zj";
		tablero[filas-2][1] = "";
		int j;
		for(j=2; j<idProductos.length + 2; j++) {
			tablero[filas-2][j] = "";
		}
		
		for(int k=j; k<cantidadVariables + j; k++) {
			tablero[filas-2][k] = "";
		}
		
		tablero[filas-2][columnas - 2] = " ";		
		tablero[filas-2][columnas - 1] = "###";
		
		//**************** FILA n ******************//
		
		tablero[filas-1][0] = "Cj-Zj";
		tablero[filas-1][1] = "";
		
		for(j=2; j<idProductos.length + 2; j++) {
			tablero[filas-1][j] = "";
		}
		for(int k=j; k<cantidadVariables + j; k++) {
			tablero[filas-1][k] = "";
		}
				
		tablero[filas-1][columnas - 2] = "###";		
		tablero[filas-1][columnas - 1] = "###";
		
		
		return tablero;
					
	}
	
	
	public String[][] iterar(String[][] tablaNueva, int iteracion) {
		System.out.println("ENTRE A ITERAR");
		try {				
			System.out.println("ANTES DE OBTENER MAYOR POSITIVO");
			//Obtener mayor positivo Cj-Zj (No se estan considerando empates)
			double max = 0;
			int columna = 0;
			for(int j=2; j<columnas; j++) {				
				if(Util.esNumero(tablaNueva[filas - 1][j]) && Double.parseDouble(tablaNueva[filas - 1][j]) > max) {					
					max = Double.parseDouble(tablaNueva[filas - 1][j]);
					System.out.println("ESTOY ASIGNANDO VALOR A MAX:" + max);
					columna = j;
				}
				
			}	
			if(max <= 0) {
				System.out.println("ESTOY ASIGNANDO NULL A TABLERO PORQUE MAX: " + max);
				tablero = null;
				return tablero; //AQUI DEBE DEVOLVER LA TABLA FINAL
			}
			System.out.println("ANTES DE OBTENER LA MENOR RAZON");
			//Obtener menor razon
			double valorMenor = Double.MAX_VALUE;
			int fila = 0;
			for(int i=2; i<filas - 2; i++) {
				System.out.println("EL VALOR AQUI ES: "+ tablaNueva[i][columnas - 1]);
				if(Double.parseDouble(tablaNueva[i][columnas - 1]) < valorMenor && valorMenor > 0) {					
					fila = i;
					valorMenor = Double.parseDouble(tablaNueva[i][columnas - 1]);
				}
			}
						
			//SALE - INGRESA
			tablaNueva[fila][1] = tablaNueva[1][columna];
			tablaNueva[fila][0] = tablaNueva[0][columna];
			
			//Elemento Pivote
			double pivote = Double.parseDouble(tablaNueva[fila][columna]); 
			
			//Obtener nueva fila pivote
			for(int j=2; j<columnas - 1; j++) {
				tablaNueva[fila][j] = (Double.parseDouble(tablaNueva[fila][j]) / pivote) + "";
			}
			
			//Obtener el resto de filas
			for(int i=2; i<filas - 2; i++) {
				double coeficiente = Double.parseDouble(tablaNueva[i][columna]);
				if(i != fila){
					for(int j=2; j<columnas - 1; j++) {
						System.out.println("LA FILA ES: "+ i);
						System.out.println("LA COLUMNA ES: "+ j );
						System.out.println("LA FILA PIVOTE ES: "+ fila);
						System.out.println("LA COLUMNA PIVOTE ES: "+columna);
						System.out.println("EL COEFICIENTE PIVOTE ES: "+ coeficiente);
						System.out.println("LA OPERACION ES: "+ tablaNueva[i][j] + " - " + coeficiente +  "*"  +tablaNueva[fila][j]+ "\n");
						tablaNueva[i][j] = (Double.parseDouble(tablaNueva[i][j]) - coeficiente * Double.parseDouble(tablaNueva[fila][j])) + "";	
					
					}
				}				
			}
			System.out.println("ANTES DE CALCULAR Zj");
			//Calcular Zj
			for(int j=2; j<columnas - 1; j++) {		
				double valor = 0;
				for(int i=2; i<filas - 2; i++) {					
					valor += Double.parseDouble(tablaNueva[i][0]) * Double.parseDouble(tablaNueva[i][j]);										
				}	
				tablaNueva[filas - 2][j] = valor+"";
			}	
			System.out.println("ANTES DE CALCULAR Cj-Zj");
			//Calcular Cj-Zj
			
			for(int j=2; j<columnas - 2; j++) {	
				double valor = 0;
				valor += Double.parseDouble(tablaNueva[0][j]) - Double.parseDouble(tablaNueva[filas - 2][j]);
				tablaNueva[filas - 1][j] = valor+"";
			}
			
			//Obtener mayor positivo Cj-Zj (No se estan considerando empates)
			max = 0;
			columna = 0;
			for(int j=2; j<columnas; j++) {				
				if(Util.esNumero(tablaNueva[filas - 1][j]) && Double.parseDouble(tablaNueva[filas - 1][j]) > max) {
					max = Double.parseDouble(tablaNueva[filas - 1][j]);
					columna = j;
				}
				if(max <= 0) {
					return tablaNueva; //AQUI DEBE DEVOLVER LA TABLA FINAL
				}
			}
			System.out.println("ANTES DE CALCULAR LA RAZON");
			//Obtener mayor y calcular razon
			double valor = 0;
			for(int i=2; i<filas - 2; i++) {
				valor = Double.parseDouble(tablaNueva[i][columnas - 2])/Double.parseDouble(tablaNueva[i][columna]);
				tablaNueva[i][columnas - 1] = valor+"";
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("JUSTO ANTES DEL RETURN ");
		if(tablaNueva == null)
			System.out.println("ESTA RETORNANDO UN NULL ");
		tablero = tablaNueva;
		
		return tablaNueva;
		
	}
	
	
	
	public String[][] obtenerTablero(int iteracion) {
		
		if(iteracion == 0) {
			//Calcular Zj
			for(int j=2; j<columnas - 1; j++) {		
				double valor = 0;
				for(int i=2; i<filas - 2; i++) {	
					System.out.println("AQUI ESTA SALIENDO NULL: " + tablero[i][0]);
					System.out.println("AQUI ESTA SALIENDO NULL: " + tablero[i][j]);
					valor += Double.parseDouble(tablero[i][0]) * Double.parseDouble(tablero[i][j]);										
				}	
				tablero[filas - 2][j] = valor+"";
			}	
			
			//Calcular Cj-Zj
			for(int j=2; j<columnas - 2; j++) {				
				tablero[filas - 1][j] += Double.parseDouble(tablero[0][j]) - Double.parseDouble(tablero[filas - 2][j]);				
			}
			
			//Obtener mayor positivo Cj-Zj (No se estan considerando empates)
			double max = 0;
			int columna = 0;
			for(int j=2; j<columnas; j++) {				
				if(Util.esNumero(tablero[filas - 1][j]) && Double.parseDouble(tablero[filas - 1][j]) > max) {
					max = Double.parseDouble(tablero[filas - 1][j]);
					columna = j;
				}
				if(max <= 0) {
					return null; //AQUI DEBE DEVOLVER LA TABLA FINAL
				}
			}
			
			//Obtener mayor y calcular razon
			double valor = 0;
			for(int i=2; i<filas - 2; i++) {
				valor = Double.parseDouble(tablero[i][columnas - 2])/Double.parseDouble(tablero[i][columna]);
				tablero[i][columnas - 1] = valor+"";
			}
			
		}	
			
		return tablero;
	}
	
	
	
	public Hashtable<Integer, Integer> obtenerResultado(String[][] tableroFinal) {
		
		String [][] resultadoTemporal = new String[cantidadVariables][2];
		
		for(int i=2; i<cantidadVariables + 2; i++) {
			resultadoTemporal[i-2][0] = tableroFinal[i][1];
			resultadoTemporal[i-2][1] = tableroFinal[i][columnas - 2];
		}
		
		for(int i=0; i<resultadoTemporal.length; i++) {		
			System.out.println("ITERACION: " + i + "VARIABLES: " + cantidadVariables);
			System.out.println("ITERACION: " + resultadoTemporal[i][0] + " VALOR: " + resultadoTemporal[i][1]);
			if(resultadoTemporal[i][0].substring(0, 1).equalsIgnoreCase("X")) {
				resultado.put(Integer.parseInt(Util.sacarLetra(resultadoTemporal[i][0], "X")), Util.cortarDecimalesString(resultadoTemporal[i][1]));
				//IMPREIMIR REUSLTADO PAAA VERIFICAR
			}			
		}
		
		return resultado;
	}
	
	public Vector<Recurso> obtenerMaterialesTotales(int[] idProductos) {
		Vector<Recurso> recursosTemp = new Vector<Recurso>(); //Todos los recursos sin importar repeticiones
		Vector<Recurso> recursosTotales = new Vector<Recurso>(); //Todos los recursos sin repeticiones
		Vector<Recurso> recursos = null; // Recursos de un producto
		ServiceProduccion serviceProduccion = new ServiceProduccion();
	
		try {
			for(int i=0; i<idProductos.length; i++){
				recursos = new Vector<Recurso>();
				recursos = serviceProduccion.obtenerRecursosPorProducto(idProductos[i]);
				
				for(Recurso recurso : recursos) {
					recursosTemp.add(recurso);					
				}
			}
					
			for(int i=0; i<recursosTemp.size(); i++) {	
				if(recursosTotales.size() != 0) {					
					boolean flagRepetido = false;
					for(int j=0; j<recursosTotales.size(); j++) {						
						if(recursosTotales.get(j).getIdRecurso() == recursosTemp.get(i).getIdRecurso()) {
							flagRepetido = true;							
						}						
					}
					if(!flagRepetido) {
						recursosTotales.add(recursosTemp.get(i));						
					}
				} else {
					recursosTotales.add(recursosTemp.get(0));					
				}
						
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return recursosTotales;
	}
	
	
}